<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of CreditCardForm
 *
 * @author samaa
 */
class CreditCardForm extends BaseForm
{

    public function setup()
    {
        $this->setWidgets(array(
            'card_number' => new sfWidgetFormInputText(),
            'cvc'         => new sfWidgetFormInputText(),
            'expire_date' => new sfWidgetFormDate(),
            'address'     => new sfWidgetFormTextarea(),
            'zip_code'    => new sfWidgetFormInputText(),
        ));

        $this->setValidators(array(
            'card_number' => new sfValidatorString(array('max_length' => 20)),
            'cvc'        => new sfValidatorString(array('max_length'  => 10, 'required'    => false)),
            'expire_date' => new sfValidatorDate(),
            'address'     => new sfValidatorString(array('required' => false)),
            'zip_code' => new sfValidatorString(array('max_length' => 10, 'required'   => false)),
        ));

        $this->widgetSchema->setNameFormat('credit_card[%s]');

        $this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
    }

    public function configure()
    {
        $this->disableLocalCSRFProtection();
        $this->validatorSchema['card_number'] = new sfValidatorRegex(array('pattern'    => '/^[0-9]+$/', 'required'   => true, 'min_length' => 13, 'max_length' => 16, 'trim'       => true));
        $this->getValidator('card_number')->setMessage('max_length', 'Invalid credit card number');
        $this->getValidator('card_number')->setMessage('min_length', 'Invalid credit card number');
        $this->getValidator('card_number')->setMessage('invalid', 'Invalid credit card number');
        $this->getValidator('card_number')->setMessage('required', 'Please provide your credit card number');

        $this->validatorSchema['cvc'] = new sfValidatorRegex(array('pattern'    => '/^[0-9]+$/', 'required'   => true, 'min_length' => 3, 'max_length' => 4, 'trim'       => true));
        $this->getValidator('cvc')->setMessage('required', 'Please provide your CVC code');
        $this->getValidator('cvc')->setMessage('max_length', 'CVC must be less than or equal 4 digits in length');
        $this->getValidator('cvc')->setMessage('min_length', 'CVC must be more than or equal 3 digits in length');
        $this->getValidator('cvc')->setMessage('invalid', 'CVC must be 4 digits in length');

        $this->validatorSchema['zip_code'] = new sfValidatorRegex(array('pattern'    => '/^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]( )?\d[ABCEGHJKLMNPRSTVWXYZ]\d)|(\d{5}(-\d{4})?)$/i', 'required'   => true, 'min_length' => 4, 'max_length' => 20));
        $this->getValidator('zip_code')->setMessage('max_length', 'Please provide a zip code less than 20 characters long');
        $this->getValidator('zip_code')->setMessage('min_length', 'Please provide a zip code more than 4 characters long');
        $this->getValidator('zip_code')->setMessage('invalid', 'Please provide a valid zip code');
        $this->getValidator('zip_code')->setMessage('required', 'Please provide your Zip code');


        $currentYear = date("Y", time());
        $years       = range($currentYear, $currentYear + 10);
        $this->getWidget('expire_date')->setOption('years', array_combine($years, $years));
        $this->getWidget('expire_date')->setOption('empty_values', array('month' => 'Month', 'year'  => 'Year', 'day'   => 'Day'));

        $this->getWidget('expire_date')->setOption('format', '%month%-%year%');
        $this->setValidator('expire_date', new DateWithoutDayValidator());
        $this->getValidator('expire_date')->setOption('required', true);
        $this->getValidator('expire_date')->setOption('min', time());
        $this->getValidator('expire_date')->setMessage('min', 'Your credit card has expired');
        $this->getValidator('expire_date')->setMessage('required', 'Please provide your credit card expiration date');
        $this->getValidator('expire_date')->setMessage('invalid', 'Please provide a valid date');

        $this->getValidator('address')->setOption('required', true);
        $this->getValidator('address')->setOption('max_length', 250);
        $this->getValidator('address')->setMessage('required', 'Please provide your address');
        $this->getValidator('address')->setMessage('max_length', 'error long address');

        $this->validatorSchema->setOption('allow_extra_fields', true);
        $this->validatorSchema->setOption('filter_extra_fields', false);

        $this->validatorSchema->setPostValidator(new sfValidatorCallback(array('callback' => array($this, 'checkCreditCardNumber')))
        );


        $this->widgetSchema->setLabels(array('cvc'         => 'CVC', 'expire_date' => 'Expiration date'));
        $this->addFormatter('CustomFormatter');
    }

    /**
     *
     * auth the card from the payment gateway
     * @param <type> $validator
     * @param <type> $values
     * @return array values
     */
    public function checkCreditCardNumber($validator, $values)
    {

        if ($values['card_number'] && $values['cvc'] && $values['zip_code'] && $values['expire_date'] && $values['address'])
        {
            //create credit card object to use in validation
            $creditCard                 = new PgCreditCard();
            $creditCard->CardCode       = $values['cvc'];
            $creditCard->AvsStreet      = $values['address'];
            $creditCard->AvsZip         = $values['zip_code'];
            $creditCard->CardNumber     = $values['card_number'];
            $creditCard->CardExpiration = $this->getExpireDate($values['expire_date']);


            $this->creditCardData = $creditCard;

            //create dummy transaction to use in run auth only
            $transactionDetail           = new PgTransactionDetail();
            $transactionDetail->Amount   = "0.05";
            $transactionDetail->Comments = "test the credit card";

            //run auth only transaction
            $transactionRequest                 = new PgTransactionRequest();
            $transactionRequest->Details        = $transactionDetail;
            $transactionRequest->CreditCardData = $creditCard;
            $output                             = $transactionRequest->runAuthOnly();

            //get information from the output
            $resultCode = $output->ResultCode;
            $errorCode  = $output->ErrorCode;


            if ($resultCode != "A")
            {
                //incase of error
                throw new sfValidatorError($this->validatorSchema['card_number'], usaepayErrorHandlee::getErrorMessage($errorCode));
            }
        }


        //mandatory for callback functions
        return $values;
    }

    /**
     *
     * @return creditCardData object used by the company to add payment methode
     */
    public function getCreditCardData()
    {
        return $this->creditCardData;
    }

    /**
     *
     * @param date $pDate
     * @return date in the formt of expiration date
     */
    public function getExpireDate($pDate)
    {
        return date('my', strtotime($pDate));
    }

    public function payProducts($price)
    {
        //create dummy transaction to use in run auth only
        $transactionDetail           = new PgTransactionDetail();
        $transactionDetail->Amount   = $price;
        $transactionDetail->Comments = "pay products bill";

        //run sale only transaction
        $transactionRequest                 = new PgTransactionRequest();
        $transactionRequest->Details        = $transactionDetail;
        $transactionRequest->CreditCardData = $this->getCreditCardData();
        $output                             = $transactionRequest->runSale();
        //get information from the output
        $resultCode = $output->ResultCode;
        $errorCode  = $output->ErrorCode;


        if ($resultCode != "A")
        {
            $return = false;
        }
        else
        {
            //close the batch
            $batch  = new PgBatch();
            $batch->closeBatch($output->BatchRefNum);
            $return = $output;
        }

        return $return;
    }

}
